"""
虽然我们这个项目【我们以后大部分场景操作】都是查询，但是难免需要进行更新【update】 插入【insert】等操作。
- 所以数据库操作需要经常重复使用，所以要封装。== 函数 或者 类 ？
- 因为可能一个数据库操作里会有多个方法【增加 修改 查询等方法】，就应该封装类。

封装类的思路和步骤：
第一步：是否定义init函数？
   - init函数目的： 定义实例属性
   - 定义实例的属性好处： 可以使用多个实例方法的共享。--调用实例属性。
   - 数据库类的封装： 查询 插入方法等都需要先链接数据库 并需要使用游标进行执行。--连接和游标就是共享
第二步： 定义实例方法，思考需要定义哪些方法？
   - 查询方法
   - 其他方法可以以后扩展。
第三步： 封装查询方法： ==函数封装
    函数封装步骤： 任何功能代码都可以封装函数。
1、先把功能代码写出来 【逻辑】
2、 def，封装函数
3、参数化，变化的数据参数化 ：不是固定，用户输入的数据，从其他地方获取数据等
4、判断是否需要返回值，return定义返回值
  - 很多时候，print出来的东西都是可以定位返回值

第四步： 因为数据库的链接有可能会失败 数据库异常了；--异常捕获

第五步： 记录日志，方便后续定位问题
- 但凡你想要去print 确认数据结果的时候 加日志记录。

数据库连接信息的参数化-- 因为变化的数据。
实例化对象的时候传参。--字典解包。
"""
import allure
import pymysql
from pymysql.cursors import DictCursor
from loguru import logger

@allure.step("数据库查询的操作")
class HandleMysql:
    def __init__(self,user,password,database,port,host):
        """
        在init函数里定义了两个实例属性： conn  cursor，后续的实例方法可以共享调用
        """
        self.conn = pymysql.connect(
                    user=user,
                    password=password,
                    database=database,
                    port = port,
                    host = host,
                    charset="utf8mb4",  # 支持中文字符集
                    cursorclass=DictCursor  # 读取的数据默认变成字典的格式
)
        self.cursor = self.conn.cursor()

    def query_data(self,query_sql,match_num=1,size=None):
        """
        1、先执行sql，得到结果数量
        2、获取具体数据之前，如果数量为0 没有必要获取；如果数量>0,才去获取详细数据
        3、获取具体数据： 一条 多条 所有，谁决定获取多少数据？== 由调用方法的用户决定，那么让用户传参。
         - 可以定义一个参数：match_num =1,fetchone，match_num=2，fetchmany，match_num=-1，fetchall 【参考Jmeter】
         - 因为更多的场景是查询一条数据，所以match_num设置默认值为1 【默认参数】，用户可以不传
        4、关闭数据库操作： conn  cursor
          - 这个不管数据库是否出错了 都要执行关闭操作，这个执行代码应该放在finally里。
        :return:
        """
        try:
            result = self.cursor.execute(query_sql) # 获取结果数量，只有数量>0 才去查询具体的数据
            logger.info(f"查询结果的条数是{result}")
            if result > 0:
                if match_num==1:
                    data = self.cursor.fetchone()
                    logger.info(f"数据库查询结果数据是：{data}")
                    return data
                elif match_num==2:
                    data = self.cursor.fetchmany(size)
                    logger.info(f"数据库查询结果数据是：{data}")
                    return data
                elif match_num==-1:
                    data = self.cursor.fetchall()
                    logger.info(f"数据库查询结果数据是：{data}")
                    return data
            else:
                logger.info(f"数据库没有查询到任何结果！")
        except Exception as err:
            logger.error(f"数据库操作异常！！{err}")
        finally: # 不管数据库是否异常 都要关闭。
            self.cursor.close()
            self.conn.close()


if __name__ == '__main__':
    from data.my_db import my_db
    sql = 'select user_phone,mobile_code from tz_sms_log where user_phone = "13555554444" order by rec_date desc;'
    # 数据库的链接信息存在一个字典里-方便读取
    # my_db = {
    #     "user": "lemon_auto",
    #     "password": "lemon!@123",
    #     "database": "yami_shops",
    #     "port": 3306,
    #     "host": "mall.lemonban.com"
    # }
    # 先实例化对象 然后调用实例方法
    # handle_mysql = HandleMysql(**my_db)  #实例化对象
    # result= handle_mysql.query_data(sql)  # 调用实例方法
    sql = """select status from tz_order where order_number = "1762098974103441408";"""
    result = HandleMysql(**my_db).query_data(sql)

    print(result)

